import React from 'react';
import PropTypes from 'prop-types';
import { Select } from '@teamix/ui';
import Overlay from './overlay.jsx';
import PathEllipsis from 'components/pathEllipsis';
import './index.scss';
import exceed from 'utils/apimap';
import utils from 'utils';
import KEYCODE from 'utils/keycode';

// const { organization } = window.FORCE;
import intl from '../../locale';

function preventDefault(e) {
  e.preventDefault();
}
const { organization } = window.FORCE;

export default class GroupSelect extends React.Component {
  static propTypes = {
    onChange: PropTypes.func,
    // 切换后的回调，可以处理：比如设置其他地方的公开性
    okFn: PropTypes.func,
    selectRef: PropTypes.func,
    // 组是否必选
    isGroupRequired: PropTypes.bool,
    // 是否支持自定义输入
    autoComplete: PropTypes.bool,
    // 类型：create-新建, transfer-设置转移
    operateType: PropTypes.oneOf(['create', 'transfer']),
    // 操作对象类型 代码库-repo 代码组-group
    type: PropTypes.oneOf(['repo', 'group']),
    // 告知父组件是否需要进行组必选校验
    setGroupNeedValidate: PropTypes.func,
    // 弹层的属性
    popupProps: PropTypes.object,
    // 是否是转移组，查组要按字母排序
    isTransfer: PropTypes.bool,
    // 是不是使用路径
    isUsePath: PropTypes.bool,
    // 是不是过滤当前父组及当前组子组
    isFilterSelf: PropTypes.bool,
    // 是否有跳转组,跳转后到我的组并打开弹窗
    hasGoGroup: PropTypes.bool,
    // 是否是devops项目,devops点击新建代码组新开窗口到我的代码组，出现新建代码组弹窗
    isDevops: PropTypes.bool,
    // 打开创建组弹窗
    goGroupModalFn: PropTypes.func,
    // 是否有新建代码组的权限
    hasCreateGroupAccess: PropTypes.bool,
    // 组数据获取成功的回调
    initFn: PropTypes.func,
  };

  static defaultProps = {
    onChange: () => {},
    okFn: () => {},
    selectRef: () => {},
    isGroupRequired: undefined,
    autoComplete: false,
    operateType: 'create',
    type: 'repo',
    setGroupNeedValidate: () => {},
    popupProps: {},
    isTransfer: false,
    isUsePath: false,
    isFilterSelf: false,
    hasGoGroup: false,
    goGroupModalFn: () => {},
    hasCreateGroupAccess: false,
    initFn: () => {},
  };

  constructor(props) {
    super(props);

    this.state = {
      isPopVisible: false,
      selectValue: '',
      dataSource: [],
      isLoading: [],
      is_group_required: false,
      highlightKey: null,
    };
  }

  componentDidMount() {
    this.getRepoSetting();
  }

  componentDidUpdate(prevProps) {
    if (prevProps.projectModalSetValue !== this.props.projectModalSetValue) {
      const { projectModalSetValue } = this.props;
      this.getGroups();
      this.handleSelect({
        label: projectModalSetValue.name,
        value: projectModalSetValue.id,
        path_with_namespace: projectModalSetValue.name_with_namespace,
        visibility_level: projectModalSetValue.visibility_level,
      });
    }
  }

  getRepoSetting = () => {
    const { value, autoComplete } = this.props;
    exceed
      .fetch({
        api: 'organization.repo.setting.get',
        params: {
          org_id: organization.id,
        },
      })
      .then((result) => {
        const { is_group_required } = result;
        // 是否有不选择分组项 --> 不做默认勾选(导入列表中需要有默认值)
        let selectValue = '';
        // if (is_group_required) {
        //   selectValue = value ? Number(value) : '';
        // } else {
        //   selectValue = Number(value);
        // }
        if (autoComplete) {
          selectValue = value || '';
        }
        this.setState(
          {
            is_group_required,
            selectValue,
          },
          () => {
            this.getGroups();
          },
        );
        this.props.setGroupNeedValidate(is_group_required);
      })
      .fail((err) => {
        console.error(err);
      });
  };

  getNamespace = () => {
    exceed
      .fetch({
        api: 'projects.namespace.my',
      })
      .then(() => {})
      .fail((err) => {
        this.setState({
          isLoading: false,
        });

        console.error(err);
      });
  };

  // @params page页码 search 搜索词
  getGroups = (page = 1, search = '') => {
    const { dataSource, is_group_required } = this.state;
    const {
      type,
      operateType,
      autoComplete,
      isTransfer,
      isUsePath,
      isFilterSelf,
      visibility_level,
    } = this.props;
    const { pathResource } = window.FORCE;
    this.setState({
      isLoading: true,
    });

    const extraParams = {};
    if (isTransfer) {
      extraParams.order_by = 'path_with_namespace';
      extraParams.sort = 'asc';
    }

    exceed
      .fetch({
        api: 'groups.list.all.authorized',
        data: {
          search: search || '',
          namespace_id: organization.namespace_id,
          ...extraParams,
        },
      })
      .then((res) => {
        const data = res.slice(1) || [];
        let result =
          visibility_level !== undefined
            ? data.filter((v) => Number(v.visibility_level) === visibility_level)
            : data;
        // 转移过滤当前父组和子组
        if (isFilterSelf) {
          if (type === 'repo') {
            result = data.filter((item) => item.id !== Number(pathResource.parentId));
          } else {
            result = data.filter(
              (item) =>
                item.id !== Number(pathResource.parentId) &&
                !item.path_with_namespace.startsWith(pathResource.fullPath),
            );
          }
        }
        const allData = page === 1 ? result : [...dataSource, ...result];
        // 1.查企业设置-必选代码组：如果不必选代码组，置顶；如果必须代码组 无该选项

        if (!search && !is_group_required) {
          allData.unshift({
            value: organization.namespace_id,
            label: intl.get({
              id: 'code-assets.components.groupSelect.DoNotSelectAGroup',
              defaultMessage: '不选择分组',
            }),
            id: organization.namespace_id,
            path_with_namespace: organization.path,
            visibility_level: '10',
            is_namespace: false,
          });
        }

        // 如果是操作转移，下拉列表要排除自己
        const newNamespaceData = [];
        allData.forEach((item) => {
          const path = utils.getGroupPath(item.path_with_namespace);
          if (operateType === 'transfer') {
            const parentId =
              type === 'repo' ? Number(pathResource.parentId) : Number(pathResource.id);
            if (Number(item.id) !== parentId) {
              newNamespaceData.push({
                label:
                  Number(item.id) === Number(organization.namespace_id) || item.is_namespace
                    ? item.label
                    : path,
                value: item.id,
                path_with_namespace: item.path_with_namespace,
                visibility_level: item.visibility_level,
              });
            }
          } else {
            let label = '';
            if (autoComplete) {
              label =
                item.label ===
                intl.get({
                  id: 'code-assets.components.groupSelect.DoNotSelectAGroup',
                  defaultMessage: '不选择分组',
                })
                  ? item.label
                  : path;
            } else if (item.name) {
              // 使用路径则取路径否则取名称
              label = isUsePath ? path : item.name;
            } else {
              // 不选择分组项
              label = item.label;
            }
            newNamespaceData.push({
              // autoComplete在导入列表中只使用path_with_namespace
              label,
              value: item.id,
              path_with_namespace: item.path_with_namespace,
              visibility_level: item.visibility_level,
            });
          }
        });

        this.setState({
          dataSource: newNamespaceData,
          isLoading: false,
        });

        this.props.initFn(newNamespaceData);
      })
      .fail((err) => {
        this.setState({
          isLoading: false,
        });

        console.error(err);
      });
  };

  handleSelect = (item) => {
    this.setState({
      isPopVisible: false,
      selectValue: item.value,
    });

    this.props.onChange(item.value);
    this.props.okFn(item);
  };

  onVisibleChange = (visible) => {
    this.setState(
      {
        isPopVisible: visible,
        highlightKey: null,
      },
      () => {
        this.getGroups();
      },
    );
  };

  // autoComplete单独使用
  onChange = (value) => {
    const { dataSource } = this.state;
    this.setState({
      selectValue: value,
    });

    this.props.onChange(value);
    this.props.okFn(
      value,
      dataSource.find((item) => item.label === value),
    );
  };

  handleKeyDown = (e) => {
    const { isPopVisible, dataSource, highlightKey } = this.state;
    switch (e.keyCode) {
      case KEYCODE.UP:
        e.preventDefault();
        this.toggleHighlightItem(-1, e);
        break;
      case KEYCODE.DOWN:
        e.preventDefault();
        this.toggleHighlightItem(1, e);
        break;
      case KEYCODE.ENTER:
        e.preventDefault();
        if (isPopVisible) {
          const highlightItem = dataSource.find((item) => item.value === highlightKey);
          highlightItem && this.handleSelect(highlightItem);
        } else {
          this.setState({
            isPopVisible: true,
          });
        }
        break;
      case KEYCODE.ESC:
        e.preventDefault();
        this.setState({
          isPopVisible: false,
        });

        break;
      default:
        break;
    }
  };

  toggleHighlightItem = (dir) => {
    const { dataSource } = this.state;
    if (!this.state.isPopVisible) {
      this.setState({
        isPopVisible: true,
      });

      return;
    }

    const enabledData = dataSource.filter((item) => !item.disabled);
    const maxCount = enabledData.length;
    // When there is no enabled item
    if (!maxCount) {
      return false;
    }

    let { highlightKey } = this.state;
    let highlightIndex = -1;

    // find previous highlight index
    highlightKey !== null &&
      enabledData.some((item, index) => {
        if (item.value === highlightKey) {
          highlightIndex = index;
        }
        return highlightIndex > -1;
      });

    // toggle highlight index
    highlightIndex += dir;
    if (highlightIndex < 0) {
      highlightIndex = maxCount - 1;
    }
    if (highlightIndex >= maxCount) {
      highlightIndex = 0;
    }

    // get highlight key
    const highlightItem = enabledData[highlightIndex];
    highlightKey = highlightItem ? highlightItem.value : null;

    this.setState({
      highlightKey,
    });
  };

  render() {
    const {
      autoComplete,
      popupProps: extraPopupProps,
      popupStyle,
      operateType,
      hasGoGroup,
      isDevops,
      goGroupModalFn,
      hasCreateGroupAccess,
      isTransfer,
    } = this.props;
    const { selectValue, dataSource, isLoading, is_group_required, highlightKey } = this.state;
    const visibilityPopupContent = (
      <Overlay
        onChange={this.handleSelect}
        onMouseDown={preventDefault}
        selectValue={selectValue}
        data={dataSource}
        getGroups={this.getGroups}
        isLoading={isLoading}
        is_group_required={is_group_required}
        style={{ popupStyle }}
        operateType={operateType}
        // 高亮value
        highlightKey={highlightKey}
        handleKeyDown={this.handleKeyDown}
        hasGoGroup={hasGoGroup}
        isDevops={isDevops}
        goGroupModalFn={goGroupModalFn}
        hasCreateGroupAccess={hasCreateGroupAccess}
        isTransfer={isTransfer}
        closePopFn={() => {
          this.setState({
            isPopVisible: false,
          });
        }}
      />
    );

    const popupProps = {
      triggerClickKeycode: [13, 32], // space, enter
      ...extraPopupProps,
    };

    if (autoComplete) {
      const curDataSource = dataSource.map((item) => {
        item.originValue = item.value;
        item.value = item.label;
        return item;
      });
      return (
        <Select.AutoComplete
          {...this.props}
          popupContainer={() => document.body}
          placeholder={intl.get({
            id: 'code-assets.components.groupSelect.SelectACodeGroup',
            defaultMessage: '请选择代码组',
          })}
          value={selectValue}
          dataSource={curDataSource}
          onChange={this.onChange}
          onFocus={() => {
            if (
              selectValue ===
              intl.get({
                id: 'code-assets.components.groupSelect.DoNotSelectAGroup',
                defaultMessage: '不选择分组',
              })
            ) {
              this.onChange('');
            }
          }}
          ref={(ref) => {
            this.SelectRef = ref;
          }}
          container={(trigger) => trigger.parentNode}
          popupProps={{
            className: 'at-path-select-popup',
          }}
          itemRender={(item) => {
            const path = item.label;
            return <PathEllipsis path={path} />;
          }}
        />
      );
    }

    return (
      <Select
        {...this.props}
        placeholder={
          isTransfer
            ? intl.get({
                id: 'code-assets.components.groupSelect.SelectATransferableCodeGroup',
                defaultMessage: '请选择可转移的代码组',
              })
            : intl.get({
                id: 'code-assets.components.groupSelect.SelectACodeGroup',
                defaultMessage: '请选择代码组',
              })
        }
        visible={this.state.isPopVisible}
        onVisibleChange={this.onVisibleChange}
        value={selectValue}
        popupProps={popupProps}
        popupContent={visibilityPopupContent}
        dataSource={dataSource}
        // followTrigger
        onKeyDown={this.handleKeyDown}
      />
    );
  }
}
